import React, { useRef, useState, useEffect } from 'react'
import './index.css'
import border from '../../img/images(1)/border-day.png'
import video1 from '../../img/allvideo/视频1.mp4'
import video2 from '../../img/allvideo/视频2.mp4'
import video3 from '../../img/allvideo/视频3.mp4'
import video4 from '../../img/allvideo/视频4.mp4'
import video5 from '../../img/allvideo/视频5.mp4'
import { CaretRightOutlined, PauseOutlined } from '@ant-design/icons'
import { Canvas } from '@react-three/fiber'
import { OrbitControls, useGLTF, useAnimations, Preload } from '@react-three/drei'
import * as THREE from 'three'

function Home() {
  // 视频存储数组
  const videos = [video1, video2, video3, video4, video5]
  const [currentVideoIndex, setCurrentVideoIndex] = useState(0)
  // 动作列表与当前动作
  const [animationNames, setAnimationNames] = useState<string[]>([])
  const [currentAction, setCurrentAction] = useState<string | null>(null)
  // 常用语义动作
  const [idleAction, setIdleAction] = useState<string | null>(null)
  const [happyAction, setHappyAction] = useState<string | null>(null)
  const [sadAction, setSadAction] = useState<string | null>(null)
  // 鼠标悬停状态
  const [isHovering, setIsHovering] = useState(false);
  // 视频播放状态
  const [isPlaying, setIsPlaying] = useState(true);
  // 引入视频
  const videoRef = useRef<HTMLVideoElement>(null)
  // 视频事件
  const handleVideoEnd = () => {
    const nextIndex = (currentVideoIndex + 1) % videos.length
    setCurrentVideoIndex(nextIndex)
    setIsPlaying(true);// 新视频开始时设置为播放状态
  }
  // 点击p标签，切换视频
  const handleDotClick = (index: number) => {
    console.log('cilicindex', index)
    setCurrentVideoIndex(index)
    setIsPlaying(true);// 切换视频时设置为播放状态
    
  }
  // 处理视频播放/暂停切换
  const toPlay = () => {
    const video = videoRef.current;
    if (!video) return;
    if (isPlaying) {
      video.pause()
    } else {
      video.play().catch(error => {
        console.log('播放失败', error)
      })
    }
    setIsPlaying(!isPlaying)
  }
    useEffect(() => {
    const video = videoRef.current;
    if (!video) return;

    // 先暂停当前播放
    video.pause();
    
    // 重置视频时间
    video.currentTime = 0;
    
    // 监听视频可播放事件后再播放
    const handleCanPlay = () => {
      if (isPlaying) {
        video.play().catch(error => {
          console.warn('自动播放受限，需要用户交互:', error);
        });
      }
      // 移除事件监听器
      video.removeEventListener('canplay', handleCanPlay);
    };

    // 添加可播放事件监听
    video.addEventListener('canplay', handleCanPlay);

    // 组件卸载时清理
    return () => {
      video.removeEventListener('canplay', handleCanPlay);
      video.pause();
    };
  }, [currentVideoIndex, isPlaying]);

  // 监听播放状态
  const handlePlay = () => {
    setIsPlaying(true)
  }
  // 暂停事件
  const handlePause = () => {
    setIsPlaying(false)
  }

  return (
    <div>
      {/* 数字人3D模型显示 */}
      <div className="modelContainer">
        {/* 动作下拉选择器（左上角） */}
        <div className="animSelector">
          <select
            value={currentAction || idleAction || ''}
            onChange={(e) => setCurrentAction(e.target.value === '' ? null : e.target.value)}
          >
            <option value="" disabled>选择动作</option>
            {/* 语义动作优先展示 */}
            {idleAction && (
              <option value={idleAction}>站立</option>
            )}
            {happyAction && (
              <option value={happyAction}>开心</option>
            )}
            {sadAction && (
              <option value={sadAction}>沮丧</option>
            )}
            {animationNames
              .filter((name) => name !== idleAction && name !== happyAction && name !== sadAction)
              .map((name) => (
                <option key={name} value={name}>{name}</option>
              ))}
          </select>
        </div>
        {/* 使用 @react-three/fiber 提供的 Canvas 组件创建一个 Three.js 渲染环境 */}
        <Canvas
          // 设置相机的初始位置和视野角度
          // position: [0, 1, 3] 表示相机位于 x=0, y=1, z=3 的位置
          // fov: 50 表示相机的视野角度为 50 度
          camera={{ position: [0, 1, 3], fov: 50 }}
         
          // 当 Canvas 初始化完成后执行的回调函数
          onCreated={({ gl }) => {
            // 应用three.js官网推荐的渲染优化
            // 设置渲染器的像素比率，使其与设备的像素比率一致，避免模糊
            gl.setPixelRatio(window.devicePixelRatio)
            // 设置色调映射为 THREE.ACESFilmicToneMapping，这是一种模拟胶片色调的映射方式，能提升画面的色彩质量
            gl.toneMapping = THREE.ACESFilmicToneMapping
            // 设置色调映射的曝光度为 1.2，控制画面的明亮程度
            gl.toneMappingExposure = 1.2
            // 设置输出颜色空间为 SRGBColorSpace，确保颜色显示正确
            gl.outputColorSpace = THREE.SRGBColorSpace
          // 设置clearAlpha为0确保背景完全透明
          gl.setClearAlpha(0)
          }}
        >
          {/* 预加载所有资源，确保在渲染前所有资源都已准备好，提升渲染性能 */}
          <Preload all />
          
          {/* 优化的光照设置 */}
          {/* 添加环境光，强度为 0.5，环境光会均匀照亮场景中的所有物体 */}
          <ambientLight intensity={0.5} />
          {/* 添加平行光，模拟太阳光效果 */}
          <directionalLight 
            // 设置平行光的位置
            position={[10, 10, 5]} 
            // 设置平行光的强度为 1
            intensity={1} 
            // 启用阴影投射
            castShadow 
            // 此处存在属性名错误，正确的属性名应该是 shadow-mapSize-width 为 shadow-mapSize.width，shadow-mapSize-height 为 shadow-mapSize.height
            // 设置阴影贴图的宽度为 1024
            shadow-mapSize-width={1024}
            // 设置阴影贴图的高度为 1024
            shadow-mapSize-height={1024}
          />
          {/* 添加另一个平行光，从相反方向照亮场景，增加场景的层次感 */}
          <directionalLight 
            // 设置平行光的位置
            position={[-10, -10, -5]} 
            // 设置平行光的强度为 0.5
            intensity={0.5} 
          />
          
          {/* 移除背景平面，使用透明背景 */}
          
          {/* 渲染数字人模型组件 */}
          <DigitalHumanModel
            onAnimationsLoaded={(names) => {
              setAnimationNames(names)
              // 提取语义动作映射
              const lower = names.map(n => ({ n, l: n.toLowerCase() }))
              const findByKeywords = (keywords: string[], cnKeywords: string[]) => {
                const hit = lower.find(({ n, l }) =>
                  keywords.some(k => l.includes(k)) || cnKeywords.some(k => n.includes(k))
                )
                return hit?.n || null
              }
              setIdleAction(findByKeywords(['idle', 'stand', 'breath'], ['站立', '待机', '呼吸']))
              setHappyAction(findByKeywords(['happy', 'joy', 'smile', 'cheer'], ['开心', '高兴', '喜悦']))
              setSadAction(findByKeywords(['sad', 'depress', 'down', 'cry'], ['沮丧', '难过', '伤心']))
            }}
            currentAction={currentAction}
            onActionChanged={setCurrentAction}
          />
          
          {/* 优化的控制器设置，添加轨道控制器，允许用户通过鼠标交互控制场景视角 */}
          <OrbitControls 
            // 启用缩放功能
            enableZoom={true} 
            // 禁用平移功能
            enablePan={false}
            // 设置相机的最大移动距离为 5
            maxDistance={5}
            // 设置相机的最小移动距离为 1.5
            minDistance={1.5}
            // 设置相机的最大极角为 π/2，限制相机的垂直移动范围
            maxPolarAngle={Math.PI / 2}
            // 设置阻尼系数为 0.05，使相机移动有平滑的阻尼效果
            dampingFactor={0.05}
          />
        </Canvas>
      </div>
      {/* 右侧框框区域 */}
      <div className="videoWrapper">
        {/* 视频播放区域 */}
        {/* 边框 */}
        <img src={border} alt="" className="videoBorder" />
        <div 
          className="videoPlayer"
          onMouseEnter={() => setIsHovering(true)}
          onMouseLeave={() => setIsHovering(false)}
          onClick={() => toPlay()}
        >
          <video
            src={videos[currentVideoIndex]}
            ref={videoRef}
            onEnded={handleVideoEnd}
            className="videoElement"
            autoPlay
            muted={true}
            playsInline // 移动端优化
            onPlay={handlePlay}
            onPause={handlePause}
          ></video>
          {/* 播放暂停 */}
          {
            isHovering && (
              <div
                className="playPauseButton"
              >
                {
                  isPlaying ? <PauseOutlined /> : <CaretRightOutlined />
                }
              </div>
            )
          }
        </div>
        {/* 视频切换 */}
        <div className="videoToggle">
          {
            videos.map((_, index) => {
              return <p
                className={index === currentVideoIndex ? 'videoDotActive' : 'videoDotInactive'}
                key={index}
                onClick={() => handleDotClick(index)}
              >  </p>
            })
          }

        </div>
      </div>

    </div>
  )
}

// 数字人模型组件 - 按照three.js官网最佳实践实现
function DigitalHumanModel({
  onAnimationsLoaded,
  currentAction,
  onActionChanged
}: {
  onAnimationsLoaded?: (names: string[]) => void
  currentAction: string | null
  onActionChanged?: (action: string) => void
}) {
  const groupRef = useRef<THREE.Group>(null)
  const { scene, animations } = useGLTF('/bunny+chibi+3d+model.glb', true)
  const { actions } = useAnimations(animations, groupRef)
  
  // 类型守卫：判断是否为支持 PBR 的标准/物理材质
  const isPBRMaterial = (
    mat: THREE.Material
  ): mat is THREE.MeshStandardMaterial | THREE.MeshPhysicalMaterial => {
    const flags = mat as { isMeshStandardMaterial?: boolean; isMeshPhysicalMaterial?: boolean }
    return flags.isMeshStandardMaterial === true || flags.isMeshPhysicalMaterial === true
  }
  
  // 优化模型性能
  React.useEffect(() => {
    // 对模型进行优化处理
    scene.traverse((child: THREE.Object3D) => {
      if ((child as unknown as { isMesh?: boolean }).isMesh) {
        const mesh = child as THREE.Mesh
        // 启用模型的阴影投射和接收
        mesh.castShadow = true
        mesh.receiveShadow = true
        
        // 优化材质
        const materialOrArray = mesh.material as THREE.Material | THREE.Material[] | undefined
        if (materialOrArray) {
          if (Array.isArray(materialOrArray)) {
            materialOrArray.forEach((mat) => {
              const m = isPBRMaterial(mat) ? mat : undefined
              if (m) {
                // 设置材质的金属度和粗糙度
                m.metalness = Math.min(m.metalness || 0.1, 0.3)
                m.roughness = Math.max(m.roughness || 0.5, 0.7)
                
                // 确保材质使用正确的颜色空间
                if (m.map) {
                  m.map.colorSpace = THREE.SRGBColorSpace
                }
                if (m.emissiveMap) {
                  m.emissiveMap.colorSpace = THREE.SRGBColorSpace
                }
              }
            })
          } else {
            // 单个材质处理
            if (isPBRMaterial(materialOrArray)) {
              const m = materialOrArray
              m.metalness = Math.min(m.metalness || 0.1, 0.3)
              m.roughness = Math.max(m.roughness || 0.5, 0.7)
              if (m.map) {
                m.map.colorSpace = THREE.SRGBColorSpace
              }
              if (m.emissiveMap) {
                m.emissiveMap.colorSpace = THREE.SRGBColorSpace
              }
            }
          }
        }
      }
    })
    
    // 克隆场景以避免修改原始引用
    const clonedScene = scene.clone()
    return () => {
      // 清理资源
      clonedScene.traverse((child: THREE.Object3D) => {
        if ((child as unknown as { isMesh?: boolean }).isMesh) {
          const mesh = child as THREE.Mesh
          mesh.geometry?.dispose()
          const materialOrArray = mesh.material as THREE.Material | THREE.Material[] | undefined
          if (materialOrArray) {
            if (Array.isArray(materialOrArray)) {
              materialOrArray.forEach((m) => (m as unknown as { dispose?: () => void }).dispose?.())
            } else {
              (materialOrArray as unknown as { dispose?: () => void }).dispose?.()
            }
          }
        }
      })
    }
  }, [scene])

  // 将动画名称回传给父组件
  useEffect(() => {
    if (onAnimationsLoaded) {
      const names = animations?.map(a => a.name).filter(Boolean) as string[]
      if (names && names.length) onAnimationsLoaded(names)
    }
  }, [animations, onAnimationsLoaded])

  // 根据 currentAction 播放对应动画；未选择时回退到 idle/stand
  useEffect(() => {
    if (!actions) return
    const chooseFallbackIdle = () => {
      const names = Object.keys(actions)
      const lower = names.map(n => ({ n, l: n.toLowerCase() }))
      const idle = lower.find(({ n, l }) => l.includes('idle') || l.includes('stand') || n.includes('站立'))?.n
      return idle || names[0]
    }
    const next = currentAction || chooseFallbackIdle()
    // 如果使用的是回退动作，通知父组件更新currentAction
    if (!currentAction && onActionChanged) {
      onActionChanged(next)
    }
    Object.values(actions).forEach(a => a?.fadeOut(0.2))
    const action = actions[next]
    action?.reset().fadeIn(0.2).play()
  }, [currentAction, actions, onActionChanged])
  
  return (
    <group ref={groupRef} position={[0, -0.5, 0]} scale={1} rotation={[0, 0, 0]}>
      {/* 使用group替代primitive以获得更好的控制 */}
      <primitive object={scene} />
      
      {/* 添加可选的包围盒辅助（可注释掉） */}
      {/* <boundingBoxHelper object={scene} args={[0x00ff00]} /> */}
    </group>
  )
}

// 配置GLTFLoader缓存 - 启用draco压缩支持以优化加载
useGLTF.preload('/bunny+chibi+3d+model.glb')

// 优化模型加载性能 - 添加TypeScript类型定义
// 移除未使用的类型以避免 linter 警告

export default Home

